
'use strict'

const fs = require('fs');
const path = require('path');
const dbUnit = require('../lib/dbUnit');
const hosttool = require('../lib/hosttool');
const sharp = require('sharp');
const emailUnit = require('../lib/emailUnit');


module.exports = class itemsModules {
	static async addItemAsync(userId, name, photo, description, swapItems) {
		let dateStr = hosttool.getNowTimeStr();

		let thumbnail = this.getThumbnail(photo);
		
		var dbClient = await dbUnit.getDbClientAsync();
		let sql = `INSERT INTO user_items(userId, name, photo, thumbnail,description, intime) 
					VALUES($userId, $name, $photo, $thumbnail, $description, $intime);
                  `;
    	await dbClient.run(sql, {
			$userId: userId,
			$name: name,
			$photo: photo,
			$thumbnail: thumbnail,
			$description: description,
			$intime: dateStr
		});
		var addObj = await dbClient.get("select last_insert_rowid() addId from user_items LIMIT 1;");

		await (swapItems || []).forEach(async (item, index) => {
			let itemSql = `
				insert into user_item_wantswaps (itemId,userId,name,swapOrder,intime)
				values ($itemId,$userId,$name,$order,$intime)`;

			await dbClient.run(itemSql, {
				$itemId: addObj.addId,
				$userId: userId,
				$name: item,
				$order: index,
				$intime: dateStr
			});
		});

		this.checkAutoSend(userId);
		return true;
	}

	static getThumbnail(photo) {
		var filePath = path.join(__dirname, '../public', photo);
		// sharp(inputBuffer)
		// .resize(320, 240)
		// .toFile('output.webp', (err, info) => { ... });

		// // 创建读取流
		// var readable = fs.readFileSync(filePath);

		var thumbnailPath = photo.substr(0, photo.lastIndexOf(".")) + "_thumbnail"+path.extname(filePath);
		var thumbnailFullPath = path.join(__dirname, '../public', thumbnailPath);

		sharp(filePath).resize(320, 240).toFile(thumbnailFullPath);

		return thumbnailPath;
	}

	static async getItemListAsync(userId, pageIndex, pageSize, search){
		var whereStr = "";
		var params = {};

		if(userId){
			whereStr = " and a.userId=$userId";
			params.$userId = userId;
		}

		if(search){
			whereStr += " and a.name like '%'||$search||'%'";
			params.$search = search;
		}

		let res = await dbUnit.getPageListAsync(pageIndex, pageSize, 
			"a.id,a.userId,a.name,a.photo,a.thumbnail,a.description,a.intime",
			"user_items a", 
			whereStr,
			"a.id desc", params);

		let itemIds = res.list.map(item => item.id);
		let itemIdStr = itemIds.join(",");

		let swapItems = await dbUnit.getAllAsync(`
			select name, itemId 
			from user_item_wantswaps 
			where itemId in (${itemIdStr})
			order by itemid desc, swapOrder`);
		
		res.list.forEach(item=>{
			item.swapItems = swapItems.filter(item2=>item2.itemId==item.id).map(item2=>item2.name);
		});

		return res;
	}

	static async deleteItemAsync(userId, id) {
		let sql = `delete from user_items where id=$id and userId = $userId`;
		let count = await dbUnit.execSqlAsync(sql, {
			$userId: userId,
			$id: id
		});
		return count > 0;
	}

	static async swapItemAsync(targetItemId, offerItemId, offerDetail){
		let targetItem = await dbUnit.getRecordAsync('select id,userId,name,photo,description from user_items where id=?', targetItemId);
		let offerItem = await dbUnit.getRecordAsync('select id,userId,name,photo,description from user_items where id=?', offerItemId);

		if (!targetItem) {
			throw "No targetItem";
		}
		if (!offerItem) {
			throw "No offerItem";
		}

		if (targetItem.userId == offerItem.userId) {
			throw "Can not swap yourself item";
		}

		let targetUser = await dbUnit.getRecordAsync('select id,user,email from users where id=?', targetItem.userId);
		let offerUser = await dbUnit.getRecordAsync('select id,user,email from users where id=?', offerItem.userId);
		
		if (!targetUser) {
			throw "No targetUser";
		}
		if (!offerUser) {
			throw "No offerUser";
		}

		var params = {
			$targetItemId: targetItemId,
			$targetUserId: targetUser.id,
			$targetEmail: targetUser.email,
			$offerItemId: offerItemId,
			$offerUserId: offerUser.id,
			$offerDetail: offerDetail,
			$offerEmail: offerUser.email,
			$intime: hosttool.getNowTimeStr()
		};

		await dbUnit.execSqlAsync(`
		insert into user_item_swaps_his (targetItemId,targetUserId,targetEmail,offerItemId,offerUserId,offerDetail,offerEmail,intime)
		values($targetItemId,$targetUserId,$targetEmail,$offerItemId,$offerUserId,$offerDetail,$offerEmail,$intime)`, params);

		this.sendEmail(targetItem, offerItem, targetUser, offerUser, offerDetail);
	}


	static async saveIWantAsync(userId, items) {
		await dbUnit.execSqlAsync('delete from user_wantswaps where userId=$userId', { $userId: userId });

		let nowStr = hosttool.getNowTimeStr();

		let i=0;
		await items.forEach(async item => {
			await dbUnit.execSqlAsync(`
					insert into user_wantswaps
					 (userId, keyName, intime,orderNum )
					values
					($userId, $keyName, $intime,$orderNum)`, {
				$userId: userId,
				$keyName: item,
				$intime: nowStr,
				$orderNum:i++
			});
		});

		this.checkAutoSend(userId);
	}

	static async getIWantAsync(userId) {
		let data = await dbUnit.getAllAsync(`select keyName from user_wantswaps where userId=${userId} order by orderNum`);

		return data;
	}

	static async getWantedItemsAsync() {
		let data = await dbUnit.getAllAsync(`
			select DISTINCT name 
			from (
				select keyName name from user_wantswaps
				union 
				select name from user_item_wantswaps
			) t 
			order by name;`);

		return data;
	}

	static async checkAutoSend(userId){
		let data = await dbUnit.getAllAsync(`
			select b.name offerItemName, b.Id offerItemId, b.userId offerUserId,  
				d.name targetItemName, d.Id targetItemId, d.userId targetUserId
			from user_item_wantswaps a
			inner join user_items b on a.name = b.name 
			inner join user_item_wantswaps c on b.id=c.itemId
			inner join user_items d on a.itemId = d.id and d.name=c.name
			where b.userId!=d.userId and not exists (
				select 1 from user_item_swaps_his aa where aa.targetItemId=d.Id and aa.OfferItemId=b.Id
			)`);

		await data.forEach(async item=>{
			this.swapItemAsync(item.targetItemId, item.offerItemId, "System auto suggest send Email!!!")
		});
	}

	static async getSuggestItemsAsync(userId, itemId, pageIndex, pageSize, search){
		
		let curItem = await dbUnit.getRecordAsync(`select name, userId from user_items where id=$id`, { $id: itemId });

		if(!(curItem&&curItem.userId==userId)){
			throw "No match item!!!";
		}

		var whereStr = " and c.id=$id";
		var params = {$id: itemId};

		if(search){
			whereStr += " and a.name like '%'||$search||'%'";
			params.$search = search;
		}

		let res = await dbUnit.getPageListAsync(pageIndex, pageSize, 
			"a.id,a.userId,a.name,a.photo,a.thumbnail,a.description,a.intime",
			`user_items a 
			 inner join user_item_wantswaps b on a.id = b.itemId 
			 inner join user_items c on b.name = c.name`, 
			whereStr,
			"a.id desc", params);

		let itemIds = res.list.map(item => item.id);
		let itemIdStr = itemIds.join(",");

		let swapItems = await dbUnit.getAllAsync(`
			select name, itemId 
			from user_item_wantswaps 
			where itemId in (${itemIdStr})
			order by itemid desc, swapOrder`);
		
		res.list.forEach(item=>{
			item.swapItems = swapItems.filter(item2=>item2.itemId==item.id).map(item2=>item2.name);
		});


		return res;
	}

	static sendEmail(targetItem, offerItem, targetUser, offerUser, offerDetail) {
		// todo 
		let host = 'http://127.0.0.1:8080';

		let html =`
		<h3>Your item has been offerd</h3>
		<pre>${offerDetail}</pre>
		<div>Your item: ${targetItem.name}</div>
		<img src="${host}${targetItem.photo}" style="max-width:80%;"/>

		<div>offer item: ${offerItem.name}</div>
		<img src="${host}${offerItem.photo}" style="max-width:80%;"/>`;

		emailUnit.sendMail(targetUser.email, 'Your item has been offer', 'SmartSwap', html);
	}
}
